# Web开发
# 随着PC机的兴起，软件开始主要运行在桌面上，而数据库这样的软件运行在服务器端，这种Client/Server模式简称CS架构。
# 随着互联网的兴起，人们发现，CS架构不适合Web，最大的原因是Web应用程序的修改和升级非常迅速，
# 而CS架构需要每个客户端逐个升级桌面App，因此，Browser/Server模式开始流行，简称BS架构。
# 在BS架构下，客户端只需要浏览器，应用程序的逻辑和数据都存储在服务器端。浏览器只需要请求服务器，获取Web页面，并把Web页面展示给用户即可。

# 1.HTTP协议简介
# 在Web应用中，服务器把网页传给浏览器，实际上就是把网页的HTML代码发送给浏览器，让浏览器显示出来。
# 而浏览器和服务器之间的传输协议是HTTP
# Content-Type指示响应的内容，这里是text/html表示HTML网页。请注意，浏览器就是依靠Content-Type来判断响应的内容是网页还是图片，
# 是视频还是音乐。浏览器并不靠URL来判断响应的内容，所以，即使URL是http://example.com/abc.jpg，它也不一定就是图片。
# HTTP格式: 每个HTTP请求和响应都遵循相同的格式，一个HTTP包含Header和Body两部分，其中Body是可选的。
#  每个Header一行一个，换行符是\r\n。当遇到连续两个\r\n时，Header部分结束，后面的数据全部是Body。
# 当存在Content-Encoding时，Body数据是被压缩的，最常见的压缩方式是gzip，所以，看到Content-Encoding: gzip时，需要将Body数据先解压缩，
# 才能得到真正的数据。压缩的目的在于减少Body的大小，加快网络传输。


# 1. HTML简介
# HTML文档就是一系列的Tag组成，最外层的Tag是<html>。规范的HTML也包含<head>...</head>和<body>...</body>
# （注意不要和HTTP的Header、Body搞混了），由于HTML是富文档模型，所以，还有一系列的Tag用来表示链接、图片、表格、表单等等。
# CSS简介
# CSS是Cascading Style Sheets（层叠样式表）的简称，CSS用来控制HTML里的所有元素如何展现：
# JavaScript简介:
# JavaScript虽然名称有个Java，但它和Java真的一点关系没有。JavaScript是为了让HTML具有交互性而作为脚本语言添加的，
# JavaScript既可以内嵌到HTML中，也可以从外部链接到HTML中。


# 2. WSGI接口
# 最简单的Web应用就是先把HTML用文件保存好，用一个现成的HTTP服务器软件，接收用户请求，从文件中读取HTML，返回。
# Apache、Nginx、Lighttpd等这些常见的静态服务器就是干这件事情的。
# 如果要动态生成HTML，就需要把上述步骤自己来实现。不过，接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活，
# 如果我们自己来写这些底层代码，还没开始写动态HTML呢，就得花个把月去读HTTP规范。
# 正确的做法是底层代码由专门的服务器软件实现，我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、
# HTTP原始请求和响应格式，所以，需要一个统一的接口，让我们专心用Python编写Web业务。
# 这个接口就是WSGI：Web Server Gateway Interface。
# WSGI接口定义非常简单，它只要求Web开发者实现一个函数，就可以响应HTTP请求

# application()函数就是符合WSGI标准的一个HTTP处理函数，它接收两个参数：
# environ：一个包含所有HTTP请求信息的dict对象；
# start_response：一个发送HTTP响应的函数。
def application(environ, start_response):
    # 发送了HTTP响应的Header，注意Header只能发送一次，也就是只能调用一次
    # 接收两个参数，一个是HTTP响应码，一个是一组list表示的HTTP Header，每个Header用一个包含两个str的tuple表示
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello web</h1>']


# 有了WSGI，我们关心的就是如何从environ这个dict对象拿到HTTP请求信息，然后构造HTML，通过start_response()发送Header，最后返回Body。
# 整个application()函数本身没有涉及到任何解析HTTP的部分，也就是说，底层代码不需要我们自己编写，我们只负责在更高层次上考虑如何响应请求就可以了。
# 不过这个application()函数怎么调用?application()函数必须由WSGI服务器来调用。有很多符合WSGI规范的服务器，我们可以挑选一个来用。
# Python内置了一个WSGI服务器，这个模块叫wsgiref，它是用纯Python编写的WSGI服务器的参考实现。所谓“参考实现”
# 是指该实现完全符合WSGI标准，但是不考虑任何运行效率，仅供开发和测试使用。

# 如果你觉得这个Web应用太简单了，可以稍微改造一下，从environ里读取PATH_INFO，这样可以显示更加动态的内容：
def application2(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    body = '<h1>Hello, %s!</h1>' % (environ['PATH_INFO'][1:] or 'web')
    return [body.encode('utf-8')]

# 无论多么复杂的Web应用程序，入口都是一个WSGI处理函数。HTTP请求的所有输入信息都可以通过environ获得，
# HTTP响应的输出都可以通过start_response()加上函数返回值作为Body。

# 复杂的Web应用程序，光靠一个WSGI函数来处理还是太底层了，我们需要在WSGI之上再抽象出Web框架，进一步简化Web开发

# 3. 使用Web框架
# 其实一个Web App，就是写一个WSGI的处理函数，针对每个HTTP请求进行响应。
# 但是如何处理HTTP请求不是问题，问题是如何处理100个不同的URL。
# 每一个URL可以对应GET和POST请求，当然还有PUT、DELETE等请求，但是我们通常只考虑最常见的GET和POST请求。
# 一个最简单的想法是从environ变量里取出HTTP请求的信息，然后逐个判断：
# def application(environ, start_response):
#     method = environ['REQUEST_METHOD']
#     path = environ['PATH_INFO']
#     if method=='GET' and path=='/':
#         return handle_home(environ, start_response)
#     if method=='POST' and path='/signin':
#         return handle_signin(environ, start_response)
#     ...
# 只是这么写下去代码是肯定没法维护了。
# 我们需要在WSGI接口之上能进一步抽象，让我们专注于用一个函数处理一个URL，至于URL到函数的映射，就交给Web框架来做。
# 由于用Python开发一个Web框架十分容易，所以Python有上百个开源的Web框架。
# 这里我们先不讨论各种Web框架的优缺点，直接选择一个比较流行的Web框架——Flask来使用。
# 安装 pip install flask
# Flask通过Python的装饰器在内部自动地把URL和函数给关联起来
# 详见 flask_demo.py

# 除了Flask，常见的Python Web框架还有：
# Django：全能型Web框架；
# web.py：一个小巧的Web框架；
# Bottle：和Flask类似的Web框架；
# Tornado：Facebook的开源异步Web框架。


# 4. 使用模板
# Flask通过render_template()函数来实现模板的渲染。和Web框架类似，Python的模板也有很多种。
# Flask默认支持的模板是jinja2，所以我们先直接安装jinja2：
# 安装 pip install jinja2
# 最后，一定要把模板放到正确的templates目录下，templates和app.py在同级目录下：
# 详见flask_demo_mvc.py
# 在Jinja2模板中，我们用{{ name }}表示一个需要替换的变量。很多时候，还需要循环、条件判断等指令语句，在Jinja2中，用{% ... %}表示指令。
# 比如循环输出页码：
# {% for i in page_list %}
#     <a href="/page/{{ i }}">{{ i }}</a>
# {% endfor %}
# 如果page_list是一个list：[1, 2, 3, 4, 5]，上面的模板将输出5个超链接。
# 除了Jinja2，常见的模板还有：
# Mako：用<% ... %>和${xxx}的一个模板；
# Cheetah：也是用<% ... %>和${xxx}的一个模板；
# Django：Django是一站式框架，内置一个用{% ... %}和{{ xxx }}的模板
